package hservice

import (
	"crypto/md5"
	"encoding/hex"
	"encoding/json"
	// "fmt"
	// "strconv"
	// "strings"
	"sync"

	// "time"

	"advertoper/db"
	"advertoper/errorcode"

	"doubimeizhi.com/datatable"
	// // "doubimeizhi.com/utility"

	log "github.com/cihub/seelog"
)

var (
	defaultUserInfoService *UserInfoService
)

type UserInfoService struct {
	homepageInfo map[string]*DataInfo
	homepageLock *sync.RWMutex
}

func newUserInfoService() *UserInfoService {
	service := &UserInfoService{}
	service.homepageInfo = make(map[string]*DataInfo)
	service.homepageLock = new(sync.RWMutex)
	// go service.updateHomepageData()
	return service
}

func GetUserInfoService() *UserInfoService {
	if defaultUserInfoService == nil {
		defaultUserInfoService = newUserInfoService()
	}
	return defaultUserInfoService
}

//数据缓存格式
type DataInfo struct {
	Fingerprint string
	Data        *RequestData
	LastTick    int64
}

type RequestData struct {
	ContainerType int                      `json:"container_type"` //容器类型
	ContainerId   int                      `json:"container_id"`   //容器的唯一id
	ContainerName string                   `json:"container_name"` //容器的名称（大标题）
	MoreRouters   string                   `json:"more_routers"`   //容器的点击更多的路由
	Layout        map[string]interface{}   `json:"layout"`         //容器的整体布局排版风格
	Item          []map[string]interface{} `json:"item"`           //容器内元素
}

//banner返回结构
type UserBannerItem struct {
	ClickAble int    `json:"clickable"` //1:可点击,2:不可点击
	Title     string `json:"title"`
	PicUrl    string `json:"pic_url"`
	Routers   string `json:"routers"`
}

//zjnews返回结构
type UserZJNewsItem struct {
	Content           string `json:"content"`
	ClickAble         int    `json:"clickable"` //1:可点击,2:不可点击
	Routers           string `json:"routers"`
	BackgroundPicture string `json:"background_picture"`
	BackgroundColor   string `json:"background_color"`
}

//ZJMultiView返回结构
type UserZJMultiViewItem struct {
	ClickAble         int    `json:"clickable"`
	Title             string `json:"title"`
	SubTitle          string `json:"sub_title"`
	PicUrl            string `json:"pic_url"`
	BackgroundPicture string `json:"background_picture"`
	BackgroundColor   string `json:"background_color"`
	Routers           string `json:"routers"`
}

//ZJSingleView返回结构
type UserZJSingleViewItem struct {
	UserZJMultiViewItem
	AccessoryPic string `json:"accessory_pic"` //单条最右侧小图标
}

//商品列表返回结构
type UserZJGoodsListItem struct {
	UserZJMultiViewItem
	Price      int    `json:"price"`
	Unit       string `json:"unit"`
	SellNumber int    `json:"sell_number"`
}

//zjtopic返回结构
type UserZJTopicItem struct {
	UserZJMultiViewItem
}

//pageview返回结构
type UserPageViewItem struct {
	ClickAble int    `json:"clickable"` //1:可点击,2:不可点击
	Title     string `json:"title"`
	TitleId   int    `json:"title_id"`
	Routers   string `json:"routers"`
}

//秒杀返回结构
type UserZJSeckillItem struct {
	ClickAble         int        `json:"clickable"`
	Title             string     `json:"title"`
	PicUrl            string     `json:"pic_url"`
	BackgroundPicture string     `json:"background_picture"`
	BackgroundColor   string     `json:"background_color"`
	Routers           string     `json:"routers"`
	BuyRouters        string     `json:"buy_routers"`
	SeckillStart      int64      `json:"seckill_start"` //秒杀开始时间
	SeckillEnd        int64      `json:"seckill_end"`   //秒杀结束时间
	Price             int        `json:"price"`
	OriginalPrice     int        `json:"original_price"` //原价
	SellNumber        int        `json:"sell_number"`
	TotalNumber       int        `json:"total_number"`
	Share             *ShareItem `json:"share"`
}
type ShareItem struct {
	Url     string `json:"url"`
	Logo    string `json:"logo"`
	Title   string `json:"title"`
	Content string `json:"content"`
}

func (p *UserInfoService) GetHomePageData(regionCode string, versionCode, plat, source int) (uint, string, string, []*RequestData) {
	//先从总体容器布局中获得容器的列表顺序
	containerOrder := p.getContainerOrder(versionCode, plat, source)
	//遍历取到容器数据
	data := make([]*RequestData, 0)
	for _, id := range containerOrder {
		daq := datatable.NewDataTableQuery()
		daq.SetTableName("container")
		daq.PushField(&datatable.FiledItem{Alias: "container_type", Field: "container_type"})
		daq.PushField(&datatable.FiledItem{Alias: "container_name", Field: "container_name"})
		daq.PushField(&datatable.FiledItem{Alias: "more_routers", Field: "more_routers"})
		daq.PushField(&datatable.FiledItem{Alias: "layout", Field: "layout"})
		daq.PushField(&datatable.FiledItem{Alias: "item_order", Field: "item_order"})
		daq.PushCondition("container_id = ?", id)
		sql, values := daq.GenerateSQL()
		mysqlHelper := db.GetHomePageInfoMysqlHelper()
		results, err := mysqlHelper.Query(sql, values...)
		if err != nil {
			log.Errorf("query container data fail ,container_id is %d err is %s", id, err.Error())
			continue
		}
		if len(results) == 0 {
			continue
		}
		item := &RequestData{}
		item.ContainerId = id
		item.ContainerType = mysqlHelper.GetColInt(results[0], "container_type")
		item.ContainerName = mysqlHelper.GetColString(results[0], "container_name")
		item.MoreRouters = mysqlHelper.GetColString(results[0], "more_routers")

		layout := make(map[string]interface{})
		ly := results[0]["layout"].([]byte)
		json.Unmarshal(ly, &layout)
		item.Layout = layout

		itemOrder := make([]int, 0)
		io := results[0]["item_order"].([]byte)
		json.Unmarshal(io, &itemOrder)
		//从缓存中取到元素[]id对应数据
		dataItem := make([]map[string]interface{}, 0)
		switch item.ContainerType {
		case 1:
			list := GetZJBannerInfoService().UserGetBannerList(itemOrder, regionCode)
			if len(list) == 0 { //元素为空，则该容器不显示
				continue
			}
			b, _ := json.Marshal(list)
			json.Unmarshal(b, &dataItem)
			item.Item = dataItem
		case 2:
			list := GetZJNewsInfoService().UserGetZJNewsList(itemOrder, regionCode)
			if len(list) == 0 {
				continue
			}
			b, _ := json.Marshal(list)
			json.Unmarshal(b, &dataItem)
			item.Item = dataItem
		case 3:
			list := GetZJMultiViewInfoService().UserGetZJMultiViewList(itemOrder, regionCode)
			if len(list) == 0 {
				continue
			}
			b, _ := json.Marshal(list)
			json.Unmarshal(b, &dataItem)
			item.Item = dataItem
		case 4:
			list := GetZJSingleViewInfoService().UserGetZJSingleView(itemOrder, regionCode)
			if len(list) == 0 {
				continue
			}
			b, _ := json.Marshal(list)
			json.Unmarshal(b, &dataItem)
			item.Item = dataItem
		case 5:
			list := GetZJGoodsListInfoService().UserGetZJGoodsListList(itemOrder, regionCode)
			if len(list) == 0 {
				continue
			}
			b, _ := json.Marshal(list)
			json.Unmarshal(b, &dataItem)
			for i := 0; i < len(list); i++ {
				dataItem[i]["price"] = list[i].Price
				dataItem[i]["sell_number"] = list[i].SellNumber
			}
			item.Item = dataItem
		case 7:
			list := GetZJSeckillInfoService().UserGetZJSeckillList(itemOrder, regionCode)
			if len(list) == 0 {
				continue
			}
			b, _ := json.Marshal(list)
			json.Unmarshal(b, &dataItem)
			for i := 0; i < len(list); i++ {
				dataItem[i]["seckill_start"] = list[i].SeckillStart
				dataItem[i]["seckill_end"] = list[i].SeckillEnd
				dataItem[i]["price"] = list[i].Price
				dataItem[i]["sell_number"] = list[i].SellNumber
				dataItem[i]["total_number"] = list[i].TotalNumber
			}

			item.Item = dataItem
		case 6:
			list := GetZJTopicInfoService().UserGetZJTopicList(itemOrder, regionCode)
			if len(list) == 0 {
				continue
			}
			b, _ := json.Marshal(list)
			json.Unmarshal(b, &dataItem)
			item.Item = dataItem
		}
		data = append(data, item)

	}
	//对data MD5
	fingerPrint := p.dataToMd5(data)
	return errorcode.EC_GL_SUCCESS, errorcode.Msg(errorcode.EC_GL_SUCCESS), fingerPrint, data
}

//对数据进行md5
func (p *UserInfoService) dataToMd5(data []*RequestData) string {
	md5Ctx := md5.New()
	b, _ := json.Marshal(data)
	md5Ctx.Write(b)
	cipherStr := md5Ctx.Sum(nil)

	return hex.EncodeToString(cipherStr)
}

//得到满足条件的容器列表顺序
func (p *UserInfoService) getContainerOrder(versionCode, plat, source int) []int {
	containerOrder := make([]int, 0)
	daq := datatable.NewDataTableQuery()
	daq.SetTableName("total_layout")
	daq.PushField(&datatable.FiledItem{Alias: "container_order", Field: "container_order"})
	if plat == 1 { //android
		daq.PushCondition("android_start_version <= ?", versionCode)
		daq.PushCondition("android_end_version >=  ?", versionCode)
	} else {
		daq.PushCondition("ios_start_version <= ?", versionCode)
		daq.PushCondition("ios_end_version >=  ?", versionCode)
	}
	daq.PushCondition("source =  ?", source)
	sql, values := daq.GenerateSQL()
	mysqlHelper := db.GetHomePageInfoMysqlHelper()
	results, err := mysqlHelper.Query(sql, values...)
	if err != nil {
		log.Errorf("query container_order fail ,~~~getContainerOrder,err is %s", err.Error())
		return containerOrder
	}
	if len(results) == 0 {
		return containerOrder
	}

	dt := results[0]["container_order"].([]byte)
	json.Unmarshal(dt, &containerOrder)

	return containerOrder

}
